package com.wmsafe.order.excelService;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wmsafe.order.annotation.ExcelField;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

/**
 * excel报表 通用导出类 可以应付数量大的导出
 */
public class ExcelExportServiceNew {

    /**
     * 导出数据到Excel
     *
     * @param clazz          动态指定对象的Class
     * @param yourMapper     MyBatis Plus Mapper
     * @param response       HttpServletResponse
     * @param queryWrapper   自定义的 QueryWrapper 对象
     * @param <T>            动态指定对象类型
     */
    public static <T> void exportToExcel(Class<T> clazz, BaseMapper<T> yourMapper, String filename,
                                         HttpServletResponse response, QueryWrapper<T> queryWrapper) {
        try (SXSSFWorkbook workbook = new SXSSFWorkbook()) {
            workbook.setCompressTempFiles(true);

            // 创建日期格式
            CreationHelper creationHelper = workbook.getCreationHelper();
            short dateFormat = creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss");

            // 设置日期格式
            CellStyle dateCellStyle = workbook.createCellStyle();
            dateCellStyle.setDataFormat(dateFormat);

            Field[] fields = clazz.getDeclaredFields(); // 获取动态指定对象的字段数组

            int batchSize = 500; // 每个批次查询的数据量
            int sheetSize = 3000; // 每个工作表的数据量，可以根据实际情况调整

            int rowCount = 0; // 记录当前工作表行数
            int sheetIndex = 0; // 工作表索引

            Sheet sheet = createSheetWithHeader(workbook, fields, sheetIndex);
            int rowIndex = 1;

            boolean hasNextPage = true;
            Page<T> page = new Page<>(1, batchSize); // 每次查询100条数据

            while (hasNextPage) {
                long currentTotal = (page.getCurrent() - 1) * page.getSize();
//                queryWrapper.last("LIMIT " + page.getSize() + " OFFSET " + currentTotal); // 设置下一页的分页参数

                page.setCurrent(currentTotal / batchSize + 1); // 设置当前页码
                page.setSize(batchSize); // 设置每次查询的数据量

                IPage<T> dataPage = yourMapper.selectPage(page, queryWrapper); // 使用 MyBatis Plus 分页查询数据
                List<T> dataList = dataPage.getRecords();

                if (dataList.isEmpty()) {
                    hasNextPage = false; // 数据为空，停止循环
                } else {
                    for (T data : dataList) {
                        if (rowCount == sheetSize) {
                            // 当前工作表已满，切换到下一个工作表
                            sheetIndex++;
                            sheet = createSheetWithHeader(workbook, fields, sheetIndex);
                            rowCount = 0; // 新工作表从第一行开始
                            rowIndex = 1;
                        }

                        Row row = sheet.createRow(rowIndex);

                        for (int i = 0; i < fields.length; i++) {
                            Field field = fields[i];
                            field.setAccessible(true);
                            try {
                                Object value = field.get(data);
                                Cell cell = row.createCell(i);
                                setCellValue(cell, value, dateCellStyle);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                                // 处理字段访问异常
                            }
                        }

                        rowIndex++; // 每写入一行数据，增加 rowIndex
                        rowCount++;

                        if (rowCount >= sheetSize) {
                            break; // 当前工作表已满，停止写入数据
                        }
                    }

                    page.setCurrent(dataPage.getCurrent() + 1); // 获取下一页数据
                    page.setSize(dataPage.getSize());
                }
            }

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheet.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + filename + ".xlsx");

            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
            // 处理异常情况
        }
    }


    private static Sheet createSheetWithHeader(SXSSFWorkbook workbook, Field[] fields, int sheetIndex) {
        Sheet sheet = workbook.createSheet("Data_" + (sheetIndex + 1));
        Row headerRow = sheet.createRow(0); // 创建表头行

        // 设置表头样式
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); // 设置为浅蓝色
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        headerStyle.setAlignment(HorizontalAlignment.CENTER); // 设置水平对齐方式为居中
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 设置垂直对齐方式为居中

        Font headerFont = workbook.createFont();
        headerFont.setColor(IndexedColors.WHITE.getIndex()); // 设置字体颜色为白色
        headerFont.setBold(true);
        headerStyle.setFont(headerFont);

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(field.getName()); // 将字段名称作为表头写入第一行
            cell.setCellStyle(headerStyle); // 应用样式

            ExcelField annotation = field.getAnnotation(ExcelField.class); // 获取字段上的注解
            if (annotation != null) {
                String header = annotation.header();
                if (StringUtils.isNotEmpty(header)) {
                    cell.setCellValue(header); // 重新将字段名称作为表头写入第一行
                }

                int width = annotation.width();
                sheet.setColumnWidth(i, width * 256); // 设置列宽度

                int height = annotation.height();
                headerRow.setHeightInPoints(height); // 设置列高度
            }
        }

        return sheet;
    }

    private static void setCellValue(Cell cell, Object value, CellStyle dateCellStyle) {
        if (value == null) {
            cell.setCellValue("");
        } else {
            switch (value.getClass().getSimpleName()) {
                case "LocalDateTime":
                case "Date":
                    cell.setCellValue((Date) value);
                    cell.setCellStyle(dateCellStyle); // 应用日期格式
                    break;
                case "String":
                    cell.setCellValue((String) value);
                    break;
                case "Integer":
                    cell.setCellValue((Integer) value);
                    break;
                case "Double":
                    cell.setCellValue((Double) value);
                    break;
                case "Boolean":
                    cell.setCellValue((Boolean) value);
                    break;
                default:
                    cell.setCellValue(value.toString());
                    break;
            }
        }
    }

}
